﻿using System;
using System.Web;
using System.Collections;
using System.Web.Security;
using System.IO;
using System.Text.RegularExpressions;

namespace NS12.Com.Tracking
{
    public class TrackingModule : IHttpModule
    {

        public TrackingModule()
        {

        }

        public String ModuleName
        {
            get { return "Tracking"; }
        }

        /// <summary>
        /// 
        /// </summary>
        public static Guid ImageID
        {
            get
            {
                return (Guid)(HttpContext.Current.Session["TrackingImageID"] ?? default(Guid));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static Guid JavaScriptID
        {
            get
            {
                return (Guid)(HttpContext.Current.Session["TrackJavaScriptID"] ?? default(Guid));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static String JavascriptToExecute
        {
            get
            {
                return (HttpContext.Current.Application["JavascriptToExecute" + HttpContext.Current.Session.SessionID] ?? "").ToString();
            }
            set
            {
                HttpContext.Current.Application["JavascriptToExecute" + HttpContext.Current.Session.SessionID] = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static Guid VisitorID
        {
            get
            {
                if (HttpContext.Current.Session["TrackingVisitorID"] == null)
                    HttpContext.Current.Session["TrackingVisitorID"] = Guid.NewGuid();

                return (Guid)(HttpContext.Current.Session["TrackingVisitorID"] ?? default(Guid));
            }
        }


        // In the Init function, register for HttpApplication 
        // events by adding your handlers.
        public void Init(HttpApplication application)
        {
            application.BeginRequest += (new EventHandler(Application_BeginRequest));
            application.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
            application.Error += new System.EventHandler(context_Error);
            application.EndRequest += (new EventHandler(Application_EndRequest));
        }

        // Your BeginRequest event handler.
        private void Application_BeginRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            if (application.Request.RawUrl.Contains(".aspx") || application.Request.RawUrl.Contains(".htm") || application.Request.RawUrl.Contains(".txt"))
            {
                application.Response.Filter = new MikeKappel.Com.CS.HttpModules.StreamFilter(application.Response.Filter, new TrackingFilterer());
            }
        }
        private void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            if (sender is HttpApplication && (sender as HttpApplication).Context.Session != null)
            {

                HttpApplication context = sender as HttpApplication;
                MikeKappel.Com.CS.RewrittenUri uri = new MikeKappel.Com.CS.RewrittenUri(context.Request.Url);

                if (uri.LocalPath == TrackingFilterer.ImageFile)
                    TrackingImage(context);
                if (uri.LocalPath.Contains("/" + VisitorID.ToString() + "/") || uri.LocalPath.Contains("/Pulse/"))
                    TrackingJavscript(context);

                if (context.Request.UserHostAddress != "::1"
                && ImageID != default(Guid)
                && JavaScriptID != default(Guid)
                && uri.File.Extension != MikeKappel.Com.CS.RewrittenUri.FileExtensionType.asmx)
                {
                    using (StreamWriter sw = File.AppendText(context.Server.MapPath("/logs/") + DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0') + ".log"))
                    {
                        sw.WriteLine(
                            context.Request.UserHostAddress + "|" +
                            uri.OriginalString + "|" +
                            context.Request.ServerVariables["ALL_RAW"] ?? ""
                            );
                    }

                    String dir1 = context.Server.MapPath("/logs/IP/") + context.Request.UserHostAddress + "\\";
                    if (!Directory.Exists(dir1))
                        Directory.CreateDirectory(dir1);

                    using (StreamWriter sw = File.AppendText(dir1 + DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0') + ".log"))
                    {
                        sw.WriteLine(uri.OriginalString);
                    }

                    String dir2 = context.Server.MapPath("/logs/Date/") + DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0') + "\\";
                    if (!Directory.Exists(dir2))
                        Directory.CreateDirectory(dir2);
                    using (StreamWriter sw = File.AppendText(dir2 + context.Request.UserHostAddress + ".log"))
                    {
                        sw.WriteLine(uri.OriginalString);
                    }
                }
                try
                {
                    //LinkToTrackerDataContext lttdc = new LinkToTrackerDataContext();
                    //Guid? trackCookieID = (HttpContext.Current.Session["TrackCookieID"] != null) ? (Guid)HttpContext.Current.Session["TrackCookieID"] : default(Guid);
                    //Guid? trackJavaScriptID = (HttpContext.Current.Session["TrackJavaScriptID"] != null) ? (Guid)HttpContext.Current.Session["TrackJavaScriptID"] : default(Guid);
                    //Guid? trackBrowsersID = (HttpContext.Current.Session["TrackBrowsersID"] != null) ? (Guid)HttpContext.Current.Session["TrackBrowsersID"] : default(Guid);
                    //Guid? trackVisitorID = (HttpContext.Current.Session["TrackVisitorID"] != null) ? (Guid)HttpContext.Current.Session["TrackVisitorID"] : default(Guid);
                    //String result = "";
                    //lttdc.spMK_Track(
                    //    context.Request.ServerVariables["ALL_RAW"] ?? "",
                    //     context.Request.UserAgent ?? "",
                    //     context.Request.ServerVariables["HTTP_REFERER"] ?? "",
                    //     context.Request.Url.OriginalString,
                    //     context.Request.Url.OriginalString,
                    //   context.Session.SessionID,
                    //   context.Request.UserHostAddress,
                    //   (context.User.Identity.IsAuthenticated) ? (Guid)Membership.GetUser().ProviderUserKey : default(Guid),
                    //   trackCookieID,
                    //   ref trackBrowsersID,
                    //   ref trackVisitorID,
                    //   ref result
                    //   );
                    //context.Session["TrackCookieID"] = trackCookieID;
                    //context.Session["TrackJavaScriptID"] = trackJavaScriptID;
                    //context.Session["TrackBrowsersID"] = trackBrowsersID;
                    //context.Session["TrackVisitorID"] = trackVisitorID;

                    //if (!String.IsNullOrEmpty(result))
                    //{
                    //    context.Response.Write(result);
                    //    context.Response.Flush();
                    //    context.Response.End();
                    //}
                }
                catch (Exception ex)
                {
                    HandleError(context, ex);
                }
            }
        }
        public void context_Error(object sender, EventArgs e)
        {
            if (sender is HttpApplication)
            {
                // At this point we have information about the error
                HttpApplication context = (HttpApplication)sender;
                HandleError(context, context.Server.GetLastError());
                context.Server.ClearError();
            }
        }
        // Your EndRequest event handler.
        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
        }

        public void Dispose()
        {
        }
        public static void TrackingJavscript(HttpApplication context)
        {
            if (context.Session["TrackJavaScriptID"] == null)
                context.Session["TrackJavaScriptID"] = Guid.NewGuid();

            context.Response.ContentType = "text/plain";
            context.Response.StatusCode = 200;
            context.Response.Write(JavascriptToExecute);
            JavascriptToExecute = null;
            context.Response.End();
        }
        public static void TrackingImage(HttpApplication context)
        {
            if (context.Session["TrackingImageID"] == null)
                context.Session["TrackingImageID"] = Guid.NewGuid();
            context.Response.AppendHeader("P3P", "CP=\"CAO PSA OUR\"");
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            MikeKappel.Com.CS.Images.ImageDisplay(context.Response, MikeKappel.Com.CS.Images.Spacer, MikeKappel.Com.CS.Images.ImageTypes.GIF);
        }
        public static void HandleError(HttpApplication context, Exception exception)
        {
            HttpResponse response = context.Response;
            HttpRequest request = context.Request;


            using (StreamWriter sw = File.AppendText(context.Server.MapPath("/logs/") + DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0') + "Error.log"))
            {
                sw.Write(
                    "\n***************************************\n" +
                    context.Request.Url.OriginalString + "\n" +
                    context.Request.UserHostAddress + "\n" +
                    ParseError(exception) + "\n\n" +
                    (context.Request.ServerVariables["ALL_RAW"] ?? "")
                    );
            }
        }
        /// <summary>
        ///Recursively Parses an Error
        /// Gets all errors and inner exceptions
        /// </summary>
        /// <returns>All Errors</returns>
        public static String ParseError(Exception Ex)
        {
            return ParseError(Ex, "");
        }
        /// <summary>
        ///Recursively Parses an Error
        /// Gets all errors and inner exceptions
        /// </summary>
        /// <returns>All Errors</returns>
        public static String ParseError(Exception Ex, String ParsedErrorString)
        {
            if (Ex != null)
            {
                if (!String.IsNullOrEmpty(Ex.StackTrace))
                {
                    if (!(Ex is System.Web.HttpUnhandledException))
                        ParsedErrorString += Ex.Message + "\r\n" +
                            "\tStackTrace:" + Ex.StackTrace.Replace("\n", "\n\t\t   ") + "\r\n" +
                            "\tSource:\t" + Ex.Source + "\r\n\r\n";
                }
                if (Ex.InnerException != null)
                {
                    ParsedErrorString = ParseError(Ex.InnerException, ParsedErrorString);
                }
            }
            return ParsedErrorString;
        }
    }
}